/* 
 * File:   BMP.cpp
 * Author: max
 * 
 * Created on October 3, 2012, 7:22 PM
 */

#include "BMP.h"

using namespace TP::Grafica::Renderizado;

BMP::BMP(long int pAncho, long int pAlto) {
    
    // Info de archivo.
    this->header.SetType (0x4D42); // Windows Format.
    this->header.SetSize (54 + pAlto * pAncho * 3 *sizeof (unsigned char) +  pAlto * (pAncho%4)); // Tamaño en bytes del archivo.
    this->header.SetReserve1 (0);
    this->header.SetReserve2 (0);
    this->header.SetOffBits (54);
    
    // Info de imagen.
    this->header.SetBmpSize (40);
    this->header.SetBmpWidth (pAncho);
    this->header.SetBmpHeight (pAlto);
    this->header.SetBmpPlanes (1);
    this->header.SetBmpBitCount (24);
    this->header.SetBmpCompression (0);
    this->header.SetBmpSizeImage (16);
    this->header.SetBmpXPelsPerMeter (2835);
    this->header.SetBmpYPelsPerMeter (2835);
    this->header.SetBmpClrUsed (0);
    this->header.SetBmpClrImportant (0);

    this->blanco = new Pixel(255,255,255);

    this->pixels = new Pixel** [pAlto];
    for (long i = 0; i < pAlto; i++)
    {
        this->pixels[i] = new Pixel* [pAncho];
        for (long cur = 0; cur < pAncho; cur++)
            this->pixels[i][cur] = this->blanco;
    }
}

BMP::~BMP() {
    for (long i = 0; i < this->height(); i++)
        delete [] this->pixels[i];
    delete [] this->pixels;
    
    delete this->blanco;
}

const Pixel& BMP::getPixel(long int pFila, long int pColumna){
    
    if ( 0 <= pFila && pFila < this->header.GetBmpHeight() && 0 <= pColumna && pColumna <= this->header.GetBmpWidth())
        return *this->pixels[pFila][pColumna];
    else 
        return *this->blanco;
}

const Pixel& BMP::setPixel(long int pFila, long int pColumna, Pixel* pPixel){
    
    if (pColumna >= 0 && pFila >= 0 && NULL != pPixel)
        if (!( this->blanco->getR() == pPixel->getR() && this->blanco->getG() == pPixel->getG() && this->blanco->getB() == pPixel->getB()))
            this->pixels[pFila][pColumna] = pPixel;
    return *pPixel;
}

long int BMP::width(){
    return this->header.GetBmpWidth();
}

long int BMP::height(){
    return this->header.GetBmpHeight();
}

namespace TP { namespace Grafica { namespace Renderizado { 
    
    ostream& operator<< (ostream& stream, const BMP& bmp){

        stream << bmp.header;

        char caracter = (char)0;

        for (long i = bmp.header.GetBmpHeight() - 1; i >= 0  ; i--)
        {
            for (long j = 0; j < bmp.header.GetBmpWidth(); j++)
                if (NULL != bmp.pixels[i][j])
                        stream << *bmp.pixels[i][j];

            // Tas escribir la linea de pixels, escribo el padding.
            for (int cur = 0; cur < bmp.header.GetBmpWidth()%4; cur++)
                stream.write(reinterpret_cast<const char*>(&caracter), sizeof (caracter));
        }
        return stream;
    }
    
}}}


